package com.xltt.newbleclient.ble;

import android.Manifest;
import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.ScanCallback;
import android.bluetooth.le.ScanResult;
import android.content.Context;
import android.database.Cursor;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.provider.ContactsContract;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import com.qmuiteam.qmui.widget.dialog.QMUITipDialog;
import com.tbruyelle.rxpermissions2.RxPermissions;
import com.xltt.byteutil.ByteUtil;
import com.xltt.byteutil.Command;
import com.xltt.byteutil.NotificationMessage;
import com.xltt.newbleclient.MainActivity;
import com.xltt.newbleclient.R;

import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.UUID;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;

public class BluethActivity extends AppCompatActivity {

    private static final String TAG = "BluethActivity";
    public static final String FILTER_BLE_NAME = "XWatch";
    public static final String FILTER_BLE_NAME2 = "w302";
    //服务uuid
    public static UUID UUID_SERVER = UUID.fromString("0000fff2-0000-1000-8000-00805f9b34fb");
    //读的特征值¸
    public static UUID UUID_CHAR_READ = UUID.fromString("0000ffe3-0000-1000-8000-00805f9b34fb");
    //写的特征值
    public static UUID UUID_CHAR_WRITE = UUID.fromString("0000ffe4-0000-1000-8000-00805f9b34fb");
    private ListAdapter listAdapter;
    private ArrayList<BluetoothDevice> arrayList = new ArrayList();
    private BluetoothGatt mBluetoothGatt;
    private Button mSendDataBtn,mSendDataBtn2;
    private BluetoothAdapter mBluetoothAdapter;
    private boolean mIsScanning = false;
    private Queue<byte[]> dataInfoQueue = new LinkedList<>();
    public static final int MTU = 250;
    private boolean isRinging = false;
    private String username = "601832001601";
    private String password = "qwer1234";
    private String macaddress = "";
    private final String USERNAME = "username";
    private final String PASSWORD = "password";
    private final String MACADDRESS = "macaddress";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_ble);
        initViews();
        checkPermissions();
        EventBus.getDefault().register(this);//注册接收从Service发过来的msg
        username = getIntent().getStringExtra(USERNAME);
        password = getIntent().getStringExtra(PASSWORD);
        macaddress = getIntent().getStringExtra(MACADDRESS);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        stopScan();
        if(EventBus.getDefault().isRegistered(this)){
            EventBus.getDefault().unregister(this);
        }
    }


    /**
     * 发送通知消息给手表
     * @param mNotificationMessage
     */
    @Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
    public void notification(NotificationMessage mNotificationMessage){
        mDataInfoQueue.offer(mNotificationMessage);
        mBleHanlder.postDelayed(mBleRunable,3000);
    }

    private Queue<NotificationMessage> mDataInfoQueue = new LinkedList<NotificationMessage>();
    private Handler mBleHanlder = new Handler();
    private Runnable mBleRunable = new Runnable() {
        @Override
        public void run() {
            if(mDataInfoQueue.peek() != null){
                //1.获取数据进行发送
                NotificationMessage mNotificationMessage = mDataInfoQueue.poll();
                String pkg = mNotificationMessage.getPackageName();
                String title = mNotificationMessage.getTitle();
                String content = mNotificationMessage.getContent();
                Log.d("zhanghui","准备发送数据 = " + mNotificationMessage.toString());
                boolean sendResult = sendNotications(pkg, title, content, true);
                Log.d("zhanghui","发送数据结果 = " + sendResult);
                if(sendResult){
                    mBleHanlder.postDelayed(this,3000);
                }
            }else{
                Log.d("zhanghui","没有数据了，停止handler轮询数据");
                mBleHanlder.removeCallbacks(mBleRunable);
            }
        }
    };

    /**
     * 初始化view
     */
    private void initViews(){
        mSendDataBtn = findViewById(R.id.send_data);
        mSendDataBtn2 = findViewById(R.id.send_data2);
        ListView listView = findViewById(R.id.listView);
        listAdapter = new ListAdapter(this, R.layout.item_device, this.arrayList);
        listView.setAdapter(listAdapter);

        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
                BluetoothDevice device = arrayList.get(i);
                connect(device);
            }
        });
    }

    /**
     * 发送测试数据
     * @param characteristic
     */
    public void sendData(BluetoothGattCharacteristic characteristic) {
        if (dataInfoQueue == null || dataInfoQueue.isEmpty()) {
            Log.d(TAG,"队列没有数据了");
            return;
        }
        if (dataInfoQueue.peek() != null && characteristic != null){
            characteristic.setValue(dataInfoQueue.poll());
            boolean resultSync = mBluetoothGatt.writeCharacteristic(characteristic);
            Log.d(TAG, "发送数据结果 = " + resultSync);
            if (dataInfoQueue.peek() != null && resultSync){//还存在数据，继续发送
                new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        byte[] poll = dataInfoQueue.poll();
                        Log.d(TAG,"分包后，本次发送数据包byte长度 = " + poll.length);
                        String[] sendData = ByteUtil.getHexStrings(poll);
                        String data = Arrays.toString(sendData);
                        Log.d(TAG,"本次发送数据包byte = " + data);
                        sendData(characteristic);
                    }
                }, 500);
            }
        }

    }



    /**
     * 点击事件
     * @param view
     */
    public void clickView(View view){
        if(view.getId() == R.id.btnStart){
            startScan();
            arrayList.clear();
            listAdapter.notifyDataSetChanged();
        }else if(view.getId() == R.id.btnStop){
            stopScan();
        }else if(view.getId() == R.id.send_data){
            bindEsim(username, password, macaddress);

            //发送数据
//            if (dataInfoQueue != null) {
//                dataInfoQueue.clear();
//                byte[] data = ByteUtil.buildData();
//                Log.d(TAG,"本次发送byte总数据长度 = " + data.length);
//                dataInfoQueue = ByteUtil.splitPacketForBytes(data,MTU);
//                sendData(characteristic);
//            }
        }else if(view.getId() == R.id.send_data2){
            bindEsim(username, password, macaddress);
        }
    }

    /**
     * 绑定esim
     * @param username
     * @param password
     * @param macaddress
     */
    private void bindEsim(String username, String password, String macaddress) {
        //找到服务
        BluetoothGattService service = mBluetoothGatt.getService(UUID_SERVER);
        //拿到写的特征值
        BluetoothGattCharacteristic characteristic = service.getCharacteristic(UUID_CHAR_WRITE);
        mBluetoothGatt.setCharacteristicNotification(characteristic, true);
        byte[] data = ByteUtil2.buildData(username, password, macaddress);
        Log.d(TAG,"本次发送byte数据长度 = " + data.length);
        characteristic.setValue(data);
        boolean resultSync = mBluetoothGatt.writeCharacteristic(characteristic);
        Log.d(TAG,"发送数据结果 = " + resultSync);
    }

    /**
     * 发送通知
     * @param packageName
     * @param title
     * @param content
     * @param post
     * @return
     */
    private boolean sendNotications(String packageName, String title, String content, boolean post) {
        if(mBluetoothGatt == null ){
            updateSendDataButton(false);
            Toast.makeText(this,"蓝牙服务断开，无法发送数据，请重连蓝牙",Toast.LENGTH_LONG).show();
            return false;
        }
        //找到服务
        BluetoothGattService service = mBluetoothGatt.getService(UUID_SERVER);
        if(service == null){
            updateSendDataButton(false);
            Toast.makeText(this,"蓝牙断开，无法发送数据",Toast.LENGTH_SHORT).show();
           return false;
        }
        //拿到写的特征值
        BluetoothGattCharacteristic characteristic = service.getCharacteristic(UUID_CHAR_WRITE);
        mBluetoothGatt.setCharacteristicNotification(characteristic, true);
        int msgId = isCallMsg(packageName, title, content, post);
        byte[] data = ByteUtil2.buildNotificationData(packageName, title, content, post, msgId);
        Log.d("zhanghui","本次发送通知byte数据长度 = " + data.length);
        characteristic.setValue(data);
        boolean resultSync = mBluetoothGatt.writeCharacteristic(characteristic);
        //Log.d("zhanghui","sendData2 发送数据结果 = " + resultSync);
        return resultSync;
    }

    private int isCallMsg(String packageName, String title, String content, boolean post) {
        int msgId = Command.COMMAND_NOTIFICATION_MESSAGE;
        if (!"com.android.dialer".equals(packageName)) {
            return msgId;
        }
        if (!"".equals(title) && "来电".equals(content) && post) {
            msgId = Command.COMMAND_NOTIFICATION_INCOMING_CALL;
            Log.d(TAG,"Bevis add for COMMAND_NOTIFICATION_INCOMING_CALL");
        } else if ("未接电话".equals(title)) {
            msgId = Command.COMMAND_NOTIFICATION_INCOMING_CALL_MISSED;
            Log.d(TAG,"Bevis add for COMMAND_NOTIFICATION_INCOMING_CALL_MISSED");
        } else if (!"".equals(title) && "当前通话".equals(content)) {
            if (post) {
                msgId = Command.COMMAND_NOTIFICATION_INCOMING_CALL_ACCEPT;
                Log.d(TAG,"Bevis add for COMMAND_NOTIFICATION_INCOMING_CALL_ACCEPT");
            } else {
                msgId = Command.COMMAND_NOTIFICATION_INCOMING_CALL_HANGUP;
                Log.d(TAG,"Bevis add for COMMAND_NOTIFICATION_INCOMING_CALL_HANGUP");
            }
        } else if ("来电".equals(content) && !post) {
            msgId = Command.COMMAND_NOTIFICATION_INCOMING_CALL_REJECT;
            Log.d(TAG,"Bevis add for COMMAND_NOTIFICATION_INCOMING_CALL_REJECT");
        }
        return msgId;
    }

    /**
     * 停止ble扫描
     */
    private void stopScan(){
        if(mIsScanning && mBluetoothAdapter != null){
            mBluetoothAdapter.getBluetoothLeScanner().stopScan(scanCallback);
        }
        mIsScanning = false;
    }

    /**
     * 扫描ble设备
     */
    public void startScan() {
        BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
        mBluetoothAdapter = bluetoothManager.getAdapter();
        if (mBluetoothAdapter == null){
            Toast.makeText(this,"没有蓝牙设备",Toast.LENGTH_SHORT).show();
            return;
        }
        if(!mBluetoothAdapter.isEnabled()){
            Toast.makeText(this,"请打开蓝牙设备",Toast.LENGTH_SHORT).show();
            return;
        }
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            BluetoothLeScanner scanner = mBluetoothAdapter.getBluetoothLeScanner();
            if (scanner != null) {
                scanner.startScan(scanCallback);
            }
        } else {
            mBluetoothAdapter.startLeScan(leScanCallback);
        }
        mIsScanning = true;
    }

    /**
     * 大于等于21版本的ble扫描结果
     */
    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    private ScanCallback scanCallback = new ScanCallback() {
        @Override
        public void onScanResult(int callbackType, ScanResult result) {
            super.onScanResult(callbackType, result);
            //device就是周边的设备了
            BluetoothDevice device = result.getDevice();
            String name = device.getName();
            String address = device.getAddress();
            Log.d("zhanghui","name = " + name + ",address = " + address);
            if(TextUtils.isEmpty(name)){
                return;
            }
            if(arrayList.contains(device)){
                return;
            }
            if(name.contains(FILTER_BLE_NAME) || name.contains(FILTER_BLE_NAME2)){
                arrayList.add(device);
                listAdapter.notifyDataSetChanged();
                stopScan();
            }
        }
    };
    /**
     * 小于21版本的sdk扫描结果
     */
    private BluetoothAdapter.LeScanCallback leScanCallback = new BluetoothAdapter.LeScanCallback() {
        @Override
        public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) {
            //device就是周边的设备了
            String name = device.getName();
            String address = device.getAddress();
            Log.d("zhanghui","name = " + name + ",address = " + address);
            if(!TextUtils.isEmpty(name) && name.contains(FILTER_BLE_NAME) || name.contains(FILTER_BLE_NAME2)){
                arrayList.add(device);
                listAdapter.notifyDataSetChanged();
                stopScan();
            }
        }
    };
    /**
     * 连接ble回调
     */
    private BluetoothGattCallback bluetoothGattCallback = new BluetoothGattCallback() {
        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
            super.onConnectionStateChange(gatt, status, newState);
            mBluetoothGatt = gatt;
            if (newState == BluetoothProfile.STATE_CONNECTED) {
                Log.d(TAG, "onConnectionStateChange 连接成功");
                // 协商单次发送最大值
                mBluetoothGatt.requestMtu(MTU);
                //查找服务
//                gatt.discoverServices();
            } else if (newState == BluetoothProfile.STATE_CONNECTING) {
                Log.d(TAG, "onConnectionStateChange 连接中......");
            } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
                Log.d(TAG, "onConnectionStateChange 连接断开");
                closeBluetoothGatt();
            } else if (newState == BluetoothProfile.STATE_DISCONNECTING) {
                Log.d(TAG, "onConnectionStateChange 连接断开中......");
            }
        }

        @Override
        public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {
            super.onReadRemoteRssi(gatt, rssi, status);
            Log.d(TAG, "信号强度变动 = " + rssi + " status = " + status);
        }

        @Override
        public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) {
            super.onMtuChanged(gatt, mtu, status);
            if (status == BluetoothGatt.GATT_SUCCESS) {
                Log.d("zhanghui", "mtu 协商成功：" + mtu);
                // 发现服务
                mBluetoothGatt.discoverServices();
                updateSendDataButton(true);
            } else {
                Log.d("zhanghui", "mtu 协商失败");
                closeBluetoothGatt();
            }
        }

        @Override
        public void onServicesDiscovered(BluetoothGatt bluetoothGatt, int status) {
            super.onServicesDiscovered(bluetoothGatt, status);
            //设置读特征值的监听，接收服务端发送的数据
            /*
            BluetoothGattService service = bluetoothGatt.getService(UUID_SERVER);
            BluetoothGattCharacteristic characteristic = service.getCharacteristic(UUID_CHAR_READ);
            boolean b = bluetoothGatt.setCharacteristicNotification(characteristic, true);
            Log.d(TAG, "onServicesDiscovered 设置通知 " + b);
             */
            if (status == BluetoothGatt.GATT_SUCCESS) {
                Log.d(TAG, "onServicesDiscovered（）服务发现成功");
                // 绑定监听
                bindNotify();
            } else {
                Log.d(TAG, "onServicesDiscovered（）服务发现失败");
                closeBluetoothGatt();
            }
        }
        @Override
        public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
            super.onCharacteristicChanged(gatt, characteristic);
            String data = new String(characteristic.getValue());
            Log.d(TAG, "onCharacteristicChanged 接收到了数据 " + data);
        }
    };

    /**
     * 更新发送测试数据button
     * @param flag
     */
    private void updateSendDataButton(boolean flag){
        mSendDataBtn.post(new Runnable() {
            @Override
            public void run() {
                mSendDataBtn.setEnabled(flag);
                if(flag){
                    Toast.makeText(BluethActivity.this,"蓝牙连接成功",Toast.LENGTH_LONG).show();
                }
            }
        });
    }

    /**
     * 发现服务后，绑定服务端发送的通知
     */
    private void bindNotify(){
        BluetoothGattService service = mBluetoothGatt.getService(UUID_SERVER);
        BluetoothGattCharacteristic characteristic = service.getCharacteristic(UUID_CHAR_READ);
        mBluetoothGatt.setCharacteristicNotification(characteristic, true);
    }

    /**
     * 关闭ble通信
     */
    private void closeBluetoothGatt(){
        if(mBluetoothGatt != null){
            mBluetoothGatt.close();
            mBluetoothGatt = null;
        }
        updateSendDataButton(false);

    }

    /**
     * 连接ble蓝牙
     * @param device
     */
    private void connect(BluetoothDevice device){
        Log.d(TAG,"点击连接ble , name = " + device.getName() + ",address = " + device.getAddress());
        device.connectGatt(this, false, bluetoothGattCallback);
    }

    /**
     * 检查定位权限是否开启
     */
    private void checkPermissions(){
        RxPermissions rxPermissions = new RxPermissions(this);
        rxPermissions
                .request(Manifest.permission.ACCESS_FINE_LOCATION)
                .subscribe(granted -> {
                    if (granted) { // Always true pre-M
                        // 用户已经同意该权限
                    } else {
                        // 用户拒绝了该权限，并且选中『不再询问』
                        Log.d(TAG, "蓝牙权限授权失败");
                        finish();
                    }
                });
    }

    private QMUITipDialog loadingDialog;
    private QMUITipDialog getLoadingDialog() {
        if (loadingDialog == null) {
            this.loadingDialog = new QMUITipDialog.Builder(this)
                    .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING)
                    .create(false);
        }
        return loadingDialog;
    }

    public class ListAdapter extends ArrayAdapter {
        private Context context;
        private int resource;
        private ArrayList arrayList;

        public ListAdapter(@NonNull Context context, int resource, ArrayList arrayList) {
            super(context, resource, arrayList);
            this.context = context;
            this.resource = resource;
            this.arrayList = arrayList;
        }

        @Nullable
        @Override
        public Object getItem(int position) {
            return arrayList.get(position);
        }

        @Override
        public int getCount() {
            return arrayList.size();
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        @NonNull
        @Override
        public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
            if (convertView == null) {
                convertView = LayoutInflater.from(context).inflate(resource, parent, false);
            }
            BluetoothDevice device = (BluetoothDevice) getItem(position);
            String name = "null";
            if(!TextUtils.isEmpty(device.getName())){
                name = device.getName();
            }
            try {
                ((TextView)convertView.findViewById(R.id.title)).setText(name);
                ((TextView)convertView.findViewById(R.id.address)).setText(device.getAddress());
            } catch (Exception exp) {
            }

            return convertView;
        }
    }

}